package cn.keniykey.mc.landterritory.land.api;

import java.lang.reflect.Type;

import javax.annotation.Nullable;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public final class LandPoint implements Cloneable{
	transient static Gson gson;
	private static class LandPointJsonGosn implements JsonSerializer<LandPoint>,JsonDeserializer<LandPoint>{
		@Override
		public LandPoint deserialize(JsonElement jsonen, Type type, JsonDeserializationContext josnd)
				throws JsonParseException {
			final JsonObject jobj = jsonen.getAsJsonObject();
			final String world = jobj.get("world").getAsString();
			final int x = jobj.get("x").getAsInt();
			final int y = jobj.get("y").getAsInt();
			final int z = jobj.get("z").getAsInt();
			return new LandPoint(world, x, y, z);
		}
		@Override
		public JsonElement serialize(LandPoint point, Type type, JsonSerializationContext josns) {
			final JsonObject jobj = new JsonObject();
			jobj.addProperty("world", (String)point.world);
			jobj.addProperty("x", (int)point.x);
			jobj.addProperty("y", (int)point.y);
			jobj.addProperty("z", (int)point.z);
			return jobj;
		}
	}
	
	static {
		gson = new GsonBuilder().registerTypeAdapter(LandPoint.class, new LandPointJsonGosn()).create();
	}
	
	private String world;
	private int x,y,z;
	
	public LandPoint(String world,int x,int y,int z) {
		this.world = world; this.x = x; this.y = y; this.z = z;
	}
	public LandPoint(Location loc) {
		this(loc.getWorld().getName(),loc.getBlockX(),loc.getBlockY(),loc.getBlockZ());
	}
	
	@Override
	public LandPoint clone(){
		return new LandPoint(this.world, this.x, this.y, this.z);
	}
	@Override
	public int hashCode() {
		return (this.world.hashCode() + this.x - this.y + this.z);
	}
	@Override
    public boolean equals(Object obj) {
		if(obj == null) return false;
		if (obj == this) return true;
		if (!(obj instanceof LandPoint)) return false;
		final LandPoint point = (LandPoint) obj;
		return (this.world.equals(point.world) && this.x == point.x && this.y == point.y && this.z == point.z);
    }
	@Override
	public String toString() {
		return "[world:" + world + " x:" + x + " y:" + y + " z:" + z + "]";
	}
	
	public String toJson() {
		return gson.toJson(this);
	}
	public static LandPoint FromJson(String json) {
		return gson.fromJson(json, LandPoint.class);
	}
	
	public String getWorldName() {
		return this.world;
	}
	public int getX() {
		return this.x;
	}
	public int getY() {
		return this.y;
	}
	public int getZ() {
		return this.z;
	}
	public void setWorldName(String worldname) {
		this.world = worldname;
	}
	public void setX(int x) {
		this.x = x;
	}
	public void setY(int y) {
		this.y = y;
	}
	public void setZ(int z) {
		this.z = z;
	}
	@Nullable
	public Location toLocation() {
		final World bworld = Bukkit.getServer().getWorld(this.world);
		return bworld == null ? null : new Location(bworld, this.x, this.y, this.z);
	}
}